const ejs = require("ejs");
const path = require("path");
const fs = require("fs-extra");
const chalk = require("chalk");
const inquirer = require("inquirer");
const ora = require("ora");
// const executeCommand = require("./execa")
const spawn = require("cross-spawn");

class Generator {
  constructor(name, destDir) {
    this.name = name;
    this.destDir = destDir;
  }
  // 核心代码
  _copyFile(tmplDir, destDir, res, rootPath, callback) {
    fs.readdir(tmplDir, (err, files) => {
      if (err) throw err;

      let count = 0;
      // 计数法来判断是否遍历完成
      const checkEnd = function () {
        ++count == files.length && callback();
      };

      files.forEach((file) => {
        const filePath = path.join(tmplDir, file);
        // 当前路径的状态
        const stat = fs.statSync(filePath);
        // 文件类型
        if (stat.isFile()) {
          // 相对路径
          const relativePath = path.relative(rootPath, filePath);
          // 输出的绝对路径
          const outputAbsolutePath = path.join(destDir, relativePath);
          if (
            relativePath === "package.json" ||
            relativePath === "index.html"
          ) {
            ejs
              .renderFile(filePath, res)
              .then((response) => {
                const outputDir = path.dirname(outputAbsolutePath);
                if (!fs.existsSync(outputDir)) {
                  // 判断文件夹是否存在，不存在就创建
                  fs.ensureDirSync(outputDir);
                  // console.log(chalk.cyan(`made directories, starting with ${made}`));
                }
                // 文件输出
                fs.writeFileSync(outputAbsolutePath, response);
                // console.log(chalk.hex("#67c23a").bold(`create ---> ${outputAbsolutePath}`));
              })
              .catch((err) => {
                console.log(chalk.red(err));
              });
          } else {
            fs.readFile(filePath, "utf-8", (err, resp) => {
              if (err) throw err;
              const outputDir = path.dirname(outputAbsolutePath);
              if (!fs.existsSync(outputDir)) {
                fs.ensureDirSync(outputDir);
                // console.log(chalk.cyan(`made directories, starting with ${made}`));
              }
              fs.writeFileSync(outputAbsolutePath, resp);
              // console.log(chalk.hex("#67c23a").bold(`create ---> ${outputAbsolutePath}`));
            });
          }
          // 执行计数方法
          checkEnd();
        } else {
          // 文件夹类型递归
          this._copyFile(filePath, destDir, res, rootPath, checkEnd);
        }
      });
    });
  }
  async create() {
    const name = this.name;
    const destDir = this.destDir;
    // 创建目标目录
    await fs.ensureDirSync(destDir);
    // inquirer 询问
    inquirer
      .prompt([
        {
          type: "input",
          name: "namespace",
          message: "Please input your project namespace, such as @tencent:",
          default: "",
        },
        {
          type: "input",
          name: "description",
          message: "Please input project description:",
          default: "vue3 project template",
        },
        {
          type: "input",
          name: "author",
          message: "Author's Name",
          default: "",
        },
        {
          type: "input",
          name: "email",
          message: "Author's Email",
          default: "",
        },
        {
          type: "input",
          name: "license",
          message: "License",
          default: "MIT",
        },
      ])
      .then((res) => {
        const params = {
          fullName: res.namespace ? `${res.namespace}/${name}` : name,
          name,
          ...res,
        };
        const tmplDir = path.join(__dirname, "../templates");
        const rootPath = tmplDir;
        console.log(chalk.hex("#ff8800").bold(`\r\ncreate file start...`));
        // 开始复制文件
        const timeStart = new Date().getTime();
        const spinner = ora("Downloading...");
        const installing = ora("Installing...");
        spinner.start()
        // 模板下载
        this._copyFile(tmplDir, destDir, params, rootPath, async() => {
          // 模板下载回调
          spinner.succeed(chalk.hex('#67c23a').bold(`template download finished!  耗时${new Date().getTime() - timeStart}ms`));
          // 开始安装依赖
          const istamp = new Date();
          installing.start()
          const result = spawn("npm", ["install"], { cwd: destDir });
          // 打印安装依赖的日志
          result.stdout.on("data", (buffer) => {
            process.stdout.write(chalk.hex("#67c23a").bold(buffer));
          });
          // 监听依赖安装状态
          result.on('close', (code) => {
            if (code !== 0) {
              console.log(chalk.red('Error occurred while installing dependencies!'));
              process.exit(1);
            } else {
              console.log(chalk.hex("#67c23a").bold(`\r\nInstall finished  耗时${new Date() - istamp}ms`));
            }
            installing.stop()
            console.log(chalk.hex("#ff8800").bold(`\r\ncd ${name}`));
            console.log(chalk.hex("#ff8800").bold("\rnpm run dev"));
          })
        });
      });
  }
}
module.exports = Generator;
